/**
 * Copyright (c) [2025] [何屹林]
 *
 * 保留所有权利。
 *
 * 文件名称：logic.cpp
 * 模块功能说明：
 * 该模块实现全局的逻辑处理，作为核心中的核心，实现了所有的逻辑函数并提供了调用接口。
 *
 * 华南师范大学-计算机学院-网络工程-1班
 * 作者：何屹林-20222132023
 * 完成日期：2025年7月24日
 */

#include "logic.h"

bool Logic::clear()
{
    nonFinalizers.clear();
    grammars.clear();
    first_set.clear();
    follow_set.clear();
    recursion.clear();
    LR1Table.clear();
    getText.clear();
    NFATable.clear();
    DFATable.clear();
    MinDFATable.clear();
    LexCode.clear();
    Lexs.clear();
    return true;
}

void Logic::extend()
{
    first_set["$"] = QSet<QString>({"$"});
    if(grammars[start_sign].size()>1)
    {
        grammars[start_sign+"_new"].insert(QStringList ()<<start_sign);
        first_set[start_sign + "_new"] = first_set[start_sign];
        follow_set[start_sign+"_new"].insert("$");
        follow_set[start_sign].unite(follow_set[start_sign + "_new"]);//!!!!!
        start_sign=start_sign+"_new";
    }
}

bool Logic::analysis(QString content)
{
    if(content.isEmpty()) return false;

    clear();
    QStringList rules=content.split('\n');

    for (const auto &grammar: qAsConst(rules)) {
        QStringList wordList = grammar.split(" ");      //分离每个词
        for (int i = 0; i < wordList.size(); i++) {
            if (wordList[i] == "") {
                wordList.removeAt(i);                   //删掉空值
            }
        }
        if (wordList.size() < 3 || wordList[1] != "->") { //每规则至少有一个词在左侧一个词在右侧，size至少为3，否则有错
            //            QMessageBox::warning(this, "提示", "文法分析失败，左侧非终结符只能出现单个词，非终结符后需要有空格以及 -> 符号", QMessageBox::Yes);
            return false;
        } else {
            nonFinalizers.push_back(wordList[0]); //将非终结符放入容器
        }
    }

    QStringList begin_rule=rules[0].split(" ");
    if(!begin_rule.isEmpty()) start_sign=begin_rule[0];

    for (const auto &grammar: qAsConst(rules)) {
        QStringList wordList = grammar.split(" ");      //分离每个词
        for (int i = 0; i < wordList.size(); i++) {
            if (wordList[i] == "") {
                wordList.removeAt(i);                   //删掉空值
            }
            else{   //若为终结符，则终结符的first集合为自己
                if (!nonFinalizers.contains(wordList[i]) && wordList[i] != "->") {
                    first_set[wordList[i]].insert(wordList[i]);
                }
            }
        }
        wordList[0];
        QString nonfinal=wordList[0];
        wordList.removeAt(0);//去除非终结符本身
        wordList.removeAt(0);//去除 ->

        int lastIdx = 0;    //上一个非|符号，以下内容用于去除|
        for (int i = 1; i < wordList.size() - 1; i++) {
            if (wordList[i] == "|") {
                grammars[nonfinal].insert(wordList.mid(lastIdx, i - lastIdx));// 从上一个|之后到下一个|之前，内容全部加入grammars
                lastIdx = i + 1;//来到|的下一个符号处
            }
        }
        grammars[nonfinal].insert(wordList.mid(lastIdx, wordList.size() - lastIdx));//需要完成最后一次操作
    }

    QHash<QString, QSet<QStringList>> gTemp=grammars;

    //消除直接左递归
    for(int i=0;i<nonFinalizers.size();i++)
    {
        QSet<QStringList> left_grammar,not_left_grammar;
        QString nonfinal=nonFinalizers[i];
        for(auto g:grammars[nonfinal])
        {
            if(g[0]==nonfinal) left_grammar.insert(g.mid(1));
            else not_left_grammar.insert(g);
        }

        if (not_left_grammar.size() == 0) {
            // 死递归
            //            QMessageBox::warning(this, "提示", "文法分析失败，包含死递归文法", QMessageBox::Yes);
            return false;
        }
        else if(!left_grammar.isEmpty())
        {
            grammars[nonfinal].clear();//原文法需要清除
            for (auto right:not_left_grammar)
            {
                right.append(nonfinal+"_not_left");
                grammars[nonfinal].insert(right);
            }
            nonFinalizers.append(nonfinal+"_not_left");
            for(auto left:left_grammar)
            {
                left.append(nonfinal+"_not_left");
                grammars[nonfinal+"_not_left"].insert(left);
            }
            grammars[nonfinal + "_not_left"].insert(QStringList() << "@");
        }
    }

    //求first元素集合
    for(int i=0;i<nonFinalizers.size();i++)
    {
        first_set[nonFinalizers[i]]=get_first(nonFinalizers[i]);
    }

    get_follow();

    grammars=gTemp;
    return true;
}

bool Logic::loadLex(const QString& filePath)
{
    std::ifstream file((filePath+"/output/sample.lex").toStdString());
    std::string line;

    if (!file.is_open()) {
        return false;
    }

    while (getline(file, line)) {
        if (line.empty()) continue;
        int i = line.find('\t');
        if (i == -1){
            std::string tempStr=token_makecd.key(std::stoi(line)).toStdString();
            Lexs.push_back(Lex{line,tempStr});
        }else
            Lexs.push_back(Lex{ line.substr(0, i), line.substr(i + 1) });
    }
    file.close();
    return true;
}

void Logic::beginWork(){
    presolve();
    buildNFA();
    genNFA();
    DFA_maker();
    genDFA();
    //MinDFA_maker();
    //minDFA_maker2(nodes);
    genMiniDFA();
//    qDebug()<<"ok";
    genLexer();

    delNFAs();
}


bool Logic::compileAndRunCode(const QString& cppPath, const QStringList& exeArguments)
{

    if (!QFile::exists(cppPath))
        return 0;


    QFileInfo fileInfo(cppPath);
    QString exePath = fileInfo.path() + "/" + fileInfo.completeBaseName() + ".exe";
    QProcess compileProcess;

    QStringList compileArgs;
    compileArgs << cppPath<< "-o" << exePath ;

//    compileArgs << cppPath << "-o" << exePath;


    // 启动编译器（这里使用g++，MSVC用户需调整）
    compileProcess.start("gcc", compileArgs);

    if (!compileProcess.waitForFinished(30000)) { // 30秒超时
        qDebug() << "Compile failed:" << compileProcess.errorString();
        return 0;
    }

    // 检查编译结果
    if (compileProcess.exitCode() != 0) {
        qDebug() << "Compile error:\n" << compileProcess.readAllStandardError();
        return 0;
    }

    QProcess runProcess;
    runProcess.start(exePath, exeArguments);  // 传递参数

    if (!runProcess.waitForFinished(30000)) {
        qDebug() << "Execution failed:" << runProcess.errorString();
        return 0;
    }

    qDebug() << "Output:\n" << runProcess.readAllStandardOutput();
    qDebug() << "Errors:\n" << runProcess.readAllStandardError();
    return true;
}


QString Logic::mapToString(const QMap<QString, int>& map) {
    QString result;
    QTextStream stream(&result);

    for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
        stream << "{" << it.key() << ", " << it.value() << "}, ";
    }

    // 移除最后一个多余的逗号和空格
    if (!map.isEmpty()) {
        result.chop(2);
    }

    return result;
}

bool Logic::isSLR1()
{
    Item first_item(start_sign,*grammars[start_sign].begin(),QSet<QString>({"$"}),0);
    LR0_state first_state;
    first_state.st.insert(first_item);
    first_state=LR0_state::closure(first_state,grammars,nonFinalizers,first_set);

    LR0 lr0;
    lr0.state_hash[first_state] = lr0.size++;

    lr0.buildLR0(first_state, grammars, nonFinalizers, first_set, follow_set);

    SLR1Warning=lr0.SLR1(follow_set);
    return lr0.is_SLR1(follow_set);
}
